#include <stdlib.h>
#include <string.h>
#include "collaboration.h"
#include "listeningObject.h"

ListeningObject::ListeningObject()
{
	listeners = NULL;
	num_listeners = 0;
}

ListeningObject::~ListeningObject()
{
	if (num_listeners != 0)
	{
		free(listeners);
		num_listeners = 0;
	}
}

int ListeningObject::get_listener_pos(EventListener* ev)
{
	for (int i=0; i<num_listeners; i++)
	{
		if (listeners[i] == ev)
			return i;
	}
	
	return -1;
}

int ListeningObject::get_listener_pos(const char* name)
{
	for (int i=0; i<num_listeners; i++)
	{
		if (strcmp(listeners[i]->name(), name)==0)
			return i;
	}
	
	return -1;
}

void ListeningObject::addEventListener(EventListener* ev)
{
	if (get_listener_pos(ev) == -1) //solo agregar si ya no estaba
	{
		num_listeners++;
		EventListener** listeners_aux = (EventListener**)malloc( num_listeners*sizeof(EventListener*) );
		
		for (int i=0; i<(num_listeners-1); i++)
		{
			listeners_aux[i] = listeners[i];
		}
		
		listeners_aux[num_listeners-1] = ev;
		
		if (listeners != NULL)
			free(listeners);
			
		listeners = listeners_aux;
	}
}

void ListeningObject::removeEventListener(EventListener* ev)
{	
	if ( (num_listeners-1) == 0)
	{
		free(listeners);
		listeners = NULL;
		num_listeners = 0;
	}
	
	int pos = get_listener_pos(ev);
	if (pos != -1)
	{
		//si el elemento a eliminar no esta en la ultima posicion del vector...
		if (pos != (num_listeners-1))
		{
			//poner el elemento a eliminar en la ultima posicion del vector
			EventListener* aux = listeners[num_listeners-1];
			listeners[num_listeners-1] = listeners[pos];
			listeners[pos] = aux;
		}
		
		num_listeners--;
		
		EventListener** listeners_aux = (EventListener**)malloc( num_listeners*sizeof(EventListener*) );
		
		for (int i=0; i<num_listeners; i++)
		{
			listeners_aux[i] = listeners[i];
		}
		
		free(listeners);
		
		listeners = listeners_aux;
	}
}

void ListeningObject::removeEventListener(const char* name)
{
	if ( (num_listeners-1) == 0)
	{
		free(listeners);
		listeners = NULL;
		num_listeners = 0;
	}
	
	int pos = get_listener_pos(name);
	while (pos != -1) //para eliminar los listeners con igual nombre
	{
		//si el elemento a eliminar no esta en la ultima posicion del vector...
		if (pos != (num_listeners-1))
		{
			//poner el elemento a eliminar en la ultima posicion del vector
			EventListener* aux = listeners[num_listeners-1];
			listeners[num_listeners-1] = listeners[pos];
			listeners[pos] = aux;
		}
		
		num_listeners--;
		
		EventListener** listeners_aux = (EventListener**)malloc( num_listeners*sizeof(EventListener*) );
		
		for (int i=0; i<num_listeners; i++)
		{
			listeners_aux[i] = listeners[i];
		}
		
		free(listeners);
		
		listeners = listeners_aux;
		
		pos = get_listener_pos(name); //actualizar la posicion del listener
	}
}

void ListeningObject::listen(const GenericObject& data)
{
	Event* ev = new Event();
	if (!ev->from_any(data))
	{
		delete ev;
		return;
	}
	
	for(int i=0; i<num_listeners; i++)
	{
		if (listeners[i]->check_event(ev))
		{
			listeners[i]->action((void*)this, ev);
		}
	}
	
	delete ev;
}
